/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.inmp.task;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.jms.JMSException;

import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;

import com.sinodata.bsm.common.vo.CollectField;
import com.sinodata.bsm.common.vo.Property;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResPropertyValue;
import com.sinodata.bsm.common.vo.ResPropertyValue.PropValue;
import com.sinodata.bsm.inmp.cache.CacheFactory;
import com.sinodata.bsm.inmp.cache.CollectFieldCache;
import com.sinodata.bsm.inmp.cache.PropertyCache;
import com.sinodata.bsm.inmp.cache.ResCache;
import com.sinodata.bsm.inmp.cache.ResTypeCache;
import com.sinodata.bsm.inmp.conf.ConfManager;
import com.sinodata.bsm.inmp.conf.HisPropConf;
import com.sinodata.bsm.inmp.conf.InmpPropBean;
import com.sinodata.bsm.inmp.message.Messenger;
import com.sinodata.bsm.inmp.util.DBConnectionUtil;

/**
 * <p>
 * Description: 历史指标获取JOB
 * :通过查询数据库实现
 * </p>
 *
 * @author wangyazhou
 * @version 1.0
   
 * <p>
 * History: 
 * 
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-11-16 上午11:34:57          wangyazhou        1.0         To create
 * </p>
 * 
 * @since   
 * @see     
 */
@SuppressWarnings("deprecation")
public class HisPropJob implements StatefulJob {

    private static final Logger logger = Logger.getLogger(HisPropJob.class);

    private ResCache resCache = (ResCache) CacheFactory.getCache(ResCache.class);

    private PropertyCache propertyCache = (PropertyCache) CacheFactory.getCache(PropertyCache.class);

    private CollectFieldCache fieldCache = (CollectFieldCache) CacheFactory.getCache(CollectFieldCache.class);

    private final ResTypeCache resTypeCache = (ResTypeCache) CacheFactory.getCache(ResTypeCache.class);

    private static final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @SuppressWarnings("rawtypes")
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {

        String lastTime = null;
        Calendar cal = Calendar.getInstance();
        String now = sf.format(cal.getTime());
        try {
            lastTime = (String) this.getPersistentData("inmptime");
        } catch (Exception e) {
            lastTime = null;
        }
        if (lastTime == null || lastTime.length() == 0) {
            try {
                this.savePersistentData("inmptime", now);
            } catch (Exception e2) {
                logger.error(e2);
            }
            return;
        }

        String timeWhere = buildSql(lastTime, now);

        //        logger.info(timeWhere);

        logger.info("[TIP]\t Start to  integrate LanEasy Perf" + now);

        Set<String> set = resCache.getAllTopNodId();
        Iterator it = set.iterator();
        while (it.hasNext()) {
            String nodeId = (String) it.next();
            for (HisPropConf conf : ConfManager.getInstance().getPerfList()) {
                try {
                    try {
                        Thread.sleep(500L);
                    } catch (InterruptedException e1) {
                        logger.error(e1);
                    }
                    List<InmpPropBean> tivoliList = fetchHisProp(conf, nodeId, timeWhere);
                    send(tivoliList, conf);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error(e);
                    continue;
                }
            }
        }

        try {
            this.savePersistentData("inmptime", now);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    /**
     * 生成查询的时间条件语句
     * @param str
     * @return
     */
    private String buildSql(String startTime, String endTime) {
        StringBuilder sb = new StringBuilder();
        sb.append("create_time >= to_date('");
        sb.append(startTime);
        sb.append("', 'yyyy-MM-dd hh24:mi:ss') and create_time <to_date('");
        sb.append(endTime);
        sb.append("', 'yyyy-MM-dd hh24:mi:ss')");
        return sb.toString();
    }

    /**
     * 持久化临时数据，例如日志文件的采集，记录上次采集的状态。与getPersistentData相应使用
     * @param key
     * @param data
     * @throws IOException
     */
    protected void savePersistentData(String key, Serializable data) throws IOException {
        File saveDir = new File("save");
        if (!saveDir.exists()) {
            saveDir.mkdir();
        }

        String fileName = "save/" + key + ".od";
        File file = new File(fileName);

        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                logger.error("failed to create new file", e);
            }
        }
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(data);
            oos.flush();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    logger.error("failed to colse ObjectOutputStream", e);
                }
            }
        }
    }

    /**
     * 获取持久化临时数据，例如日志文件的采集，记录上次采集的状态。与savePersistentData相应使用
     * @param key
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    protected Serializable getPersistentData(String key) throws IOException, ClassNotFoundException {
        String fileName = "save/" + key + ".od";
        File file = new File(fileName);
        if (!file.exists()) {
            return null;
        }
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(file));
            return (Serializable) ois.readObject();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    logger.error("failed to colse ObjectOutputStream", e);
                }
            }
        }
    }

    /**
     *  查询性能数据  并转存到inmp中
     * @param conf
     * @return
     */
    private List<InmpPropBean> fetchHisProp(HisPropConf conf, String id, String timeWhere) {

        String sql = replaceSqlParam(conf.getSql(), id, timeWhere);

        logger.info(sql);

        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        ResultSetMetaData rsMetaData = null;
        List<InmpPropBean> values = new ArrayList<InmpPropBean>();
        try {
            conn = DBConnectionUtil.getInstance().getLeConnection();
            statement = conn.createStatement();
            rs = statement.executeQuery(sql);
            if (rs == null) {
                return null;
            }
            rsMetaData = rs.getMetaData();
            int numberOfColumns = rsMetaData.getColumnCount();
            while (rs.next()) {
                InmpPropBean bean = new InmpPropBean();
                bean.setKey(rs.getString(1));
                bean.setTime(rs.getString(2));
                String[] value = new String[numberOfColumns - 2];
                for (int i = 3; i <= numberOfColumns; i++) {
                    value[i - 3] = rs.getString(i);
                }
                bean.setValues(value);
                //                //tdd
                //                System.out.println(bean.toString());
                values.add(bean);
            }
        } catch (Exception e) {
            logger.error("Error" + id, e);
            return null;
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException ex) {

                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException ex) {

                }
            }
            DBConnectionUtil.getInstance().returnConn(conn);
        }
        return values;
    }

    /**
     * 发送指标数据
     * @param beans
     * @param conf
     */
    private void send(List<InmpPropBean> beans, HisPropConf conf) {
        if (beans == null) {
            return;
        }
        for (InmpPropBean bean : beans) {
            String[] props = conf.getProps().split("[,]");
            if (props.length != bean.getValues().length) {
                continue;
            }
            ResPropertyValue value = new ResPropertyValue();
            //resid
            Res res = resCache.getResIdByIId(bean.getKey());
            if (res == null) {
                continue;
            }

            //对props进行处理 判断是CPU还是MEM
            String[] propsTmp = null;
            for (int i = 0; i < props.length; i++) {
                String[] ctmp = props[i].split("[_]");
                if (ctmp.length > 1) {
                    propsTmp = new String[props.length];
                    for (String cstr : ctmp) {
                        String[] cmtmp = cstr.split("[#]");
                        if (resTypeCache.get(res.getResTypeId()).getParentId() == Long.parseLong(cmtmp[0])) {
                            propsTmp[i] = cmtmp[1];
                            break;
                        }
                    }
                } else {
                    break; //跳出整个循环就可以
                }
            }

            if (propsTmp != null) {
                props = propsTmp;
            }

            value.setResId(res.getId());

            //
            value.setTaskId(-2L);

            Date t;
            try {
                String tt = bean.getTime();
                logger.info(tt);
                t = sf.parse(tt);
            } catch (Exception e) {
                logger.error(e);
                t = new Date();
            }

            logger.info(t.toString());

            //time
            value.setTime(t);

            //value
            List<PropValue> propValueList = new ArrayList<PropValue>();
            for (int i = 0; i < props.length; i++) {
                Long propId = Long.parseLong(props[i]);
                Property property = propertyCache.get(propId);
                if (property == null) {
                    continue;
                }
                CollectField field = fieldCache.getByPropId(propId);
                PropValue propValue = ResPropertyValue.createPropValue(propId, bean.getValues()[i], field.getFieldName());
                propValueList.add(propValue);
            }
            value.setValues(propValueList.toArray(new PropValue[propValueList.size()]));
            sendPropertyValue(value);
        }
    }

    /**
     * 发送实时指标值到center的队列中。
     */
    private void sendPropertyValue(ResPropertyValue valuex) {
        try {
            Messenger.getInstance().sendPropertyValue(valuex);
        } catch (JMSException e) {
            logger.error("failed to send property value:" + valuex, e);
        }
    }

    /**
     * 替换sql中的变量 并设置
     * @param str
     * @return
     */
    private String replaceSqlParam(String str, String id, String timeWhere) {
        str = str.replaceAll("VARJOBID", id);
        str = str.replaceAll("VARTIME", timeWhere);
        return str;
    }

    public static void main(String[] args) {
        try {
            sf.parse("2013-04-03 09:30:50");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
